package cn.edu.neu.vmmigeval.cloud.policy;

import cn.edu.neu.vmmigeval.cloud.config.Migration;
import cn.edu.neu.vmmigeval.cloud.entity.Host;
import cn.edu.neu.vmmigeval.cloud.entity.Vm;

import java.util.ArrayList;
import java.util.List;


public abstract class VmPlacementPolicy {
	private List<Host> hostList;
	private MigratedHostPolicy migratedHostPolicy;
	
	public VmPlacementPolicy(List<Host> hostList, MigratedHostPolicy migratedHostPolicy){
		this.hostList = hostList;
		this.migratedHostPolicy = migratedHostPolicy;
	}
	public VmPlacementPolicy(){
		
	}
	public VmPlacementPolicy(MigratedHostPolicy migratedHostPolicy){
		this.migratedHostPolicy = migratedHostPolicy;
	}
	
	
	public abstract List<Migration> getNewVmPlacement(List<Vm> vmsToMigrate, List<Host> hosts);
	
	public List<Host> getExcludedHosts(List<Host> hosts){
		
		List<Host> excludedHosts = new ArrayList<Host>();
		for (Host host : hosts) {
			
			if(host.getActive()==0&&!host.isMigration()){
				
				excludedHosts.add(host);
				
			}
		}
		return excludedHosts;
		
		
	}
	
	public Host findHostForVm(Vm vm, List<Host> excludedHosts,double threshold){
		
		
		int cpu = 0,ram = 0 ,bw=0,disk=0;
		
		for (Host host : excludedHosts) {
			List<Vm> vms = host.getVmList();
			if(vms!=null&&vms.size()!=0){
				for (Vm vm2 : vms) {
					cpu+=vm2.getTotalCpu();
					ram+=vm2.getTotalRam();
					bw+=vm2.getTotalBw();
					disk+=vm2.getTotalDisk();
				}
				if((vm.getTotalCpu()+cpu<=host.getTotalCpu())&&(vm.getTotalRam()+ram<=host.getTotalRam())
						&&(vm.getTotalBw()+bw<=host.getTotalBw())&&(vm.getTotalDisk()+disk<=host.getTotalDisk())){
					
					if((vm.getCurrentCpu()+host.getCurrentCpu())/host.getTotalCpu()<=threshold){
						return host;
					}
				}
			}
		}
		return null;
	}

	protected boolean isHostOverUtilizedAfterAllocation(Host host, Vm vm) {
		boolean isHostOverUtilizedAfterAllocation = true;
		Host host2 = vm.getHost();
		if (host.vmCreate(vm)) {
			isHostOverUtilizedAfterAllocation = this.getMigratedHostPolicy().isHostOverUtilized(host);
			host.vmDestroy(vm);
			vm.setHost(host2);
		}
		return isHostOverUtilizedAfterAllocation;
	}
	
	public List<Host> getHostList() {
		return hostList;
	}

	public void setHostList(List<Host> hostList) {
		this.hostList = hostList;
	}

	public MigratedHostPolicy getMigratedHostPolicy() {
		return migratedHostPolicy;
	}

	public void setMigratedHostPolicy(MigratedHostPolicy migratedHostPolicy) {
		this.migratedHostPolicy = migratedHostPolicy;
	}
	
	

}
